package com.miaoshaoproject.service.impl;

import com.miaoshaoproject.dao.ItemDOMapper;
import com.miaoshaoproject.dao.ItemStockDOMapper;
import com.miaoshaoproject.dao.StockLogDOMapper;
import com.miaoshaoproject.dataobject.ItemDO;
import com.miaoshaoproject.dataobject.ItemStockDO;
import com.miaoshaoproject.dataobject.StockLogDO;
import com.miaoshaoproject.error.BussinessException;
import com.miaoshaoproject.error.EmBussinessError;
import com.miaoshaoproject.mq.MqProducer;
import com.miaoshaoproject.service.CacheService;
import com.miaoshaoproject.service.model.ItemModel;
import com.miaoshaoproject.service.model.PromoModel;
import com.miaoshaoproject.service.ItemService;
import com.miaoshaoproject.service.PromoService;
import com.miaoshaoproject.validate.ValidationResult;
import com.miaoshaoproject.validate.ValidatorImpl;
import org.apache.rocketmq.client.exception.MQBrokerException;
import org.apache.rocketmq.client.exception.MQClientException;
import org.apache.rocketmq.client.producer.SendResult;
import org.apache.rocketmq.remoting.exception.RemotingException;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Service
public class ItemServiceImpl  implements ItemService {

     @Autowired
     private ValidatorImpl validator;
     @Autowired
     private ItemDOMapper itemDOMapper;
     @Autowired
     private ItemStockDOMapper itemStockDOMapper;
     @Autowired
     private PromoService promoService;
     @Autowired
     private RedisTemplate redisTemplate;
     @Autowired
     private MqProducer producer;
     @Autowired
     private StockLogDOMapper stockLogDOMapper;
     @Autowired
     private CacheService cacheService;

     private ItemDO convertItemDOFromItemModel(ItemModel itemModel){
         if(itemModel==null){
             return  null;
         }
         ItemDO itemDO=new ItemDO();
         BeanUtils.copyProperties(itemModel,itemDO);
         return itemDO;
     }
    private ItemStockDO convertItemStockDOFromItemModel(ItemModel itemModel){
        if(itemModel==null){
            return  null;
        }
        ItemStockDO itemStockDO=new ItemStockDO();
        itemStockDO.setItemId(itemModel.getId());
        itemStockDO.setStock(itemStockDO.getStock());
        return itemStockDO;
    }
    @Override
    @Transactional
    public ItemModel createItem(ItemModel itemModel) throws BussinessException {
        //校验入参
        ValidationResult result=validator.validate(itemModel);
        if(result.isHasErrors()){
            throw new BussinessException(EmBussinessError.PARAMETER_VALIDATION_ERROR,result.getErrMsg());
        }
        //转化itemModel--》dataobject
         ItemDO itemDO=this.convertItemDOFromItemModel(itemModel);

        //写入数据库
        itemDOMapper.insertSelective(itemDO);
        itemModel.setId(itemDO.getId());
        ItemStockDO itemStockDO=this.convertItemStockDOFromItemModel(itemModel);
        itemStockDOMapper.insertSelective(itemStockDO);
        //返回创建完成的对象
        return this.getItemById(itemModel.getId());
    }

    @Override
    public List<ItemModel> listItem() {
         List<ItemDO> itemDOList=itemDOMapper.listItem();
         List<ItemModel> itemModelList=itemDOList.stream().map(itemDO -> {
             ItemStockDO itemStockDO=itemStockDOMapper.selectByItemId(itemDO.getId());
             ItemModel itemModel=this.convertModelFromDataObject(itemDO,itemStockDO);
             return itemModel;
         }).collect(Collectors.toList());
         return itemModelList;
    }

    @Override
    public ItemModel getItemById(Integer id) {
         ItemDO itemDO=itemDOMapper.selectByPrimaryKey(id);
         if(itemDO==null){
              return null;
         }
         //操作库存数量
         ItemStockDO itemStockDO=itemStockDOMapper.selectByItemId(itemDO.getId());
         //将dataobject-->model
         ItemModel itemModel=convertModelFromDataObject(itemDO,itemStockDO);
         //获取活动商品信息
        PromoModel promoModel= promoService.getPromoByItemId(itemModel.getId());
        if (promoModel!=null && promoModel.getStatus().intValue()!=3){
           itemModel.setPromoModel(promoModel);
        }

         return itemModel;
    }



    private ItemModel convertModelFromDataObject(ItemDO itemDO,ItemStockDO itemStockDO){
         ItemModel itemModel=new ItemModel();
         BeanUtils.copyProperties(itemDO,itemModel);
         itemModel.setStock(itemStockDO.getStock());
         return  itemModel;
    }

    @Override
    @Transactional
    public boolean decreaseStock(Integer itemId, Integer amount) throws BussinessException {
        //int affectedRow=itemStockDOMapper.decreaseStock(itemId,amount);
        long result=redisTemplate.opsForValue().increment("promo_item_stock_"+itemId,amount.intValue()*-1);
        if(result>0){
            //库存扣减更新本地缓存和redis缓存
            ItemModel itemModel= (ItemModel) cacheService.getFromCommonCache("item_"+itemId);
            if(itemModel!=null){
                itemModel.setStock((Integer) redisTemplate.opsForValue().get("promo_item_stock_"+itemId));
                //填充redis缓存
                redisTemplate.opsForValue().set("item_"+itemId,itemModel);
                //填充本地缓存
                cacheService.setCommonCache("item_"+itemId,itemModel);
            }else{
                itemModel=(ItemModel) redisTemplate.opsForValue().get("item_"+itemId);
                if(itemModel!=null){
                    itemModel.setStock((Integer) redisTemplate.opsForValue().get("promo_item_stock_"+itemId));
                    //填充redis缓存
                    redisTemplate.opsForValue().set("item_"+itemId,itemModel);
                    //填充本地缓存
                    cacheService.setCommonCache("item_"+itemId,itemModel);
                }
            }
            //更新库存成功
            return true;
        }else if(result==0){
           //打上库存已售罄的标识
            redisTemplate.opsForValue().set("promo_item_stock_invalid_"+itemId,"true");
            //库存扣减更新本地缓存和redis缓存
            ItemModel itemModel= (ItemModel) cacheService.getFromCommonCache("item_"+itemId);
            if(itemModel!=null){
                itemModel.setStock((Integer) redisTemplate.opsForValue().get("promo_item_stock_"+itemId));
                //填充redis缓存
                redisTemplate.opsForValue().set("item_"+itemId,itemModel);
                //填充本地缓存
                cacheService.setCommonCache("item_"+itemId,itemModel);
            }else{
                itemModel=(ItemModel) redisTemplate.opsForValue().get("item_"+itemId);
                if(itemModel!=null){
                    itemModel.setStock((Integer) redisTemplate.opsForValue().get("promo_item_stock_"+itemId));
                    //填充redis缓存
                    redisTemplate.opsForValue().set("item_"+itemId,itemModel);
                    //填充本地缓存
                    cacheService.setCommonCache("item_"+itemId,itemModel);
                }
            }
            //更新库存成功
            return true;
        }else{
            //更新库存失败
            this.increaseStock(itemId,amount);
            return false;
        }

    }

    @Override
    @Transactional
    public void increaseSales(Integer itemId, Integer amount) throws BussinessException {
        itemDOMapper.increaseSales(itemId,amount);
    }

    @Override
    public ItemModel getItemByIdInCache(Integer id) {
         ItemModel itemModel= (ItemModel) redisTemplate.opsForValue().get("item_validate_"+id);
         if(itemModel==null){
             itemModel=this.getItemById(id);
             redisTemplate.opsForValue().set("item_validate_"+id,itemModel);
             redisTemplate.expire("item_validate_"+id,10,TimeUnit.MINUTES);
         }
         return itemModel;
    }

    @Override
    public boolean asyncDecreaseStock(Integer itemId, Integer amount) {
        boolean mqResult=producer.asyncReduceStock(itemId,amount);
        return mqResult;
    }

    @Override
    public boolean increaseStock(Integer itemId, Integer amount) {
        redisTemplate.opsForValue().increment("promo_item_stock_"+itemId,amount.intValue());
        return true;
    }

    //初始化对应的库存流水
    @Override
    @Transactional
    public String initStockLog(Integer itemId, Integer amount) {
        StockLogDO stockLogDO=new StockLogDO();
        stockLogDO.setItemId(itemId);
        stockLogDO.setAmount(amount);
        stockLogDO.setStockLogId(UUID.randomUUID().toString().replace("-",""));
        stockLogDO.setStatus(1);
        stockLogDOMapper.insertSelective(stockLogDO);
        return stockLogDO.getStockLogId();
    }
}
